/*
libimago - a multi-format image file input/output library.
Copyright (C) 2010 John Tsiombikas <nuclear@member.fsf.org>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdlib.h>
#include <string.h>
#include "ftype_module.h"

static struct list_node {
	struct ftype_module *module;
	struct list_node *next;
} *modules;

/* defined in modules.c which is generated by configure */
void img_modules_init();

static int done_init;

int img_register_module(struct ftype_module *mod)
{
	struct list_node *node;

	if(!(node = malloc(sizeof *node))) {
		return -1;
	}

	node->module = mod;
	node->next = modules;
	modules = node;
	return 0;
}

struct ftype_module *img_find_format_module(struct img_io *io)
{
	struct list_node *node;

	if(!done_init) {
		img_modules_init();
		done_init = 1;
	}

	node = modules;
	while(node) {
		if(node->module->check(io) != -1) {
			return node->module;
		}
		node = node->next;
	}
	return 0;
}

struct ftype_module *img_guess_format(const char *fname)
{
	struct list_node *node;
	char *suffix;
	int suffix_len;

	if(!done_init) {
		img_modules_init();
		done_init = 1;
	}

	if(!(suffix = strrchr(fname, '.'))) {
		return 0;	/* no suffix, can't guess ... */
	}
	suffix_len = (int)strlen(suffix);

	node = modules;
	while(node) {
		char *suflist = node->module->suffix;
		char *start, *end;

		while(*suflist) {
			if(!(start = strstr(suflist, suffix))) {
				break;
			}
			end = start + suffix_len;

			if(*end == ':' || *end == 0) {
				return node->module;	/* found it */
			}
			suflist = end;
		}

		node = node->next;
	}
	return 0;
}

struct ftype_module *img_get_module(int idx)
{
	struct list_node *node;

	if(!done_init) {
		img_modules_init();
		done_init = 1;
	}

	node = modules;
	while(node && idx--) {
		node = node->next;
	}
	return node->module;
}
